#include <GL/glew.h>
#include <mutex>

#include "../../include/drawer/drawer.hpp"
#include "../../include/result.hpp"
#include "../../include/config.hpp"
#include <iostream> // Added to include std::cerr

namespace drawer {
    // 失败时的错误回调函数
    void errorCallback(int error, const char* description) {
        std::cerr << "Error: " << description << std::endl;
    }

    // 初始化GLFW和创建窗口的函数,如果成功创建，则返回一个指针
    GLFWwindow* initWindow(int width, int height, const char* title) {
        if (!glfwInit()) {
            std::cerr << "Failed to initialize GLFW" << std::endl;
            return nullptr;
        }
        glfwSetErrorCallback(errorCallback);
        GLFWwindow* window = glfwCreateWindow(width, height, title, nullptr, nullptr);
        if (!window) {
            std::cerr << "Failed to create GLFW window" << std::endl;
            glfwTerminate();
            return nullptr;
        }
        glfwMakeContextCurrent(window);
        glewExperimental = GL_TRUE;
        if (glewInit() != GLEW_OK) {
            std::cerr << "Failed to initialize GLEW" << std::endl;
            return nullptr;
        }
        return window;
    }

    void drawDot(GLfloat red, GLfloat green, GLfloat blue, int x, int y) {
        // 设置颜色（这里设置为白色）
        glColor3f(red, green, blue);
        // 开始绘制点
        glBegin(GL_POINTS);
        glVertex2i(x, y);
        glEnd();
    }

    void drawScreen(Pixel** pixels, int width, int height) {
        glBegin(GL_POINTS);
        for (int x = 0; x <= width; ++x) {
            for (int y = 0; y <= height; ++y) {
                glColor3f(pixels[x][y].red, pixels[x][y].green, pixels[x][y].blue);
                glVertex2i(pixels[x][y].x, pixels[x][y].y);
            }
        }
        glEnd();
    }

    Result<GLFWwindow*, std::string> initDrawer(int width, int height) {
        // 初始化窗口
        GLFWwindow* window = initWindow(width, height, "GLFW Pixel Example");
        if (!window) {
            return Result<GLFWwindow*, std::string>::Err("初始化失败");
        }

        // 投影设置（确保绘制的区域和像素坐标对应）
        // 这一段请勿进行修改，这一段确保了，这个渲染器仅仅将opengl作为一个绘制点的功能，而不使用更高级的功能
        // 而对数据的处理，都是手动完成，而不是借助api
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        // 设置正交投影，左下角为 (0, 0)，右上角为 (width, height)
        glOrtho(0, width, 0, height, -1, 1);
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();

        return Result<GLFWwindow*, std::string>::Ok(window);
    }

    // 循环进行绘画
    void loopDraw(GLFWwindow* window, Screen& screen, std::mutex& screen_mutex) {
        while (!glfwWindowShouldClose(window)) {
            // 清空屏幕
            glClear(GL_COLOR_BUFFER_BIT);
            {
                std::lock_guard<std::mutex> guard(screen_mutex);
                drawScreen(screen.content, screen.width, screen.height);
            }
            // 交换缓冲
            glfwSwapBuffers(window);
            // 处理事件
            glfwPollEvents();
        }
    }

    // 清理资源
    void destroyDrawer(GLFWwindow* window) {
        glfwDestroyWindow(window);
        glfwTerminate();
    }
}